package com.xiaochuan.config;


import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;

@Configuration
public class ShiroConfig {


//    @Bean//加密
//    public HashedCredentialsMatcher hashedCredentialsMatcher(){
//        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
//        matcher.setHashAlgorithmName("md5");//指定什么类型的加密方式
//        matcher.setHashIterations(1);//加密几次
//        return matcher;
//    }

    //让shiro的注解得到加载和执行
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        autoProxyCreator.setProxyTargetClass(true);
        return autoProxyCreator;
    }

    @Bean//缓存
    public CacheManager shiroCacheManager() {
        return new MemoryConstrainedCacheManager();
    }

    @Bean//注解加载器
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager defaultWebSecurityManager) {
        AuthorizationAttributeSourceAdvisor attributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        attributeSourceAdvisor.setSecurityManager(defaultWebSecurityManager);
        return attributeSourceAdvisor;
    }

    /**
     * 配置缩写                 对应的过滤器                          功能
     * anon              AnonymousFilter                    指定url可以匿名访问
     * authc                 FormticationFilter              指定url需要form表单登录，
     * 默认会从请求中获取username、password,rememberMe等参数并尝试登录，
     * 如果登录不了就会跳转到loginUrl配置的路径。我们也可以用这个过滤器做默认的登录逻辑，
     * 但是一般都是我们自己在控制器写登录逻辑的，自己写的话出错返回的信息都可以定制嘛。
     * authcBasic            BasicHttpAuthenticationFilter      指定url需要basic登录
     * logout                LogoutFilter                       登出过滤器，配置指定url就可以实现退出功能，非常方便
     * noSessionCreation     NoSessionCreationFilter            禁止创建会话
     * perms                 PermissionsAuthorizationFilter     需要指定权限才能访问
     * port              PortFilter                         需要指定端口才能访问
     * rest              HttpMethodPermissionFilter         将http请求方法转化成相应的动词来构造一个权限字符串
     * roles                 RolesAuthorizationFilter           需要指定角色才能访问
     * ssl                   SslFilter                          需要https请求才能访问
     * user              UserFilter                         需要已登录或“记住我”的用户才能访问
     * <p>
     * 但经过实际测试，过滤器的过滤路径，是context-path下的路径，无需加上"/platform"前缀
     * chain.addPathDefinition("/my/mvnBuild", "authc,perms[mvn:install]");//需要mvn:build权限
     * chain.addPathDefinition("/my/npmClean", "authc,perms[npm:clean]");//需要npm:clean权限
     * chain.addPathDefinition("/my/docker", "authc,roles[docker]");//需要js角色
     * chain.addPathDefinition("/my/python", "authc,roles[python]");//需要python角色
     */
    @Bean//shiro过滤器
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultSecurityManager defaultSecurityManager) {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(defaultSecurityManager);
        LinkedHashMap<String, String> filterMap = new LinkedHashMap<>();

//        shiroFilter.setLoginUrl("");//身份认证失败，则跳转到登录页面的配置 没有登录的用户请求需要登录的页面时自动跳转到登录页面，不是必须的属性，不输入地址的话会自动寻找项目web项目的根目录下的”/login.jsp”页面。
//        shiroFilter.setSuccessUrl("");//登录成功默认跳转页面，不配置则跳转至”/”。如果登陆前点击的一个需要登录的页面，则在登录自动跳转到那个需要登录的页面。不跳转到此。
//        shiroFilter.setUnauthorizedUrl("");//没有权限默认跳转的页面
//        shiroFilter.setFilterChainDefinitions("");//filterChainDefinitions的配置顺序为自上而下,以最上面的为准

        //登录首页的
        filterMap.put("/index.html", "anon");
        filterMap.put("/login.html", "anon");
        filterMap.put("/login", "anon");
        filterMap.put("/logout", "logout");

        //swagger的拦截
        filterMap.put("/swagger-ui.html", "anon");
        filterMap.put("/swagger-ui/*", "anon");
        filterMap.put("/swagger-resources/**", "anon");
        filterMap.put("/v2/api-docs", "anon");
        filterMap.put("/v3/api-docs", "anon");
        filterMap.put("/webjars/**", "anon");
        //静态资源
        filterMap.put("/static/**", "anon");
        filterMap.put("/**", "authc");
        shiroFilter.setLoginUrl("/");
        shiroFilter.setFilterChainDefinitionMap(filterMap);
        return shiroFilter;

    }


    @Bean//安全管理器
    public DefaultWebSecurityManager defaultWebSecurityManager(UserRealm userRealm, CacheManager cacheManager) {
        DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager();
        defaultSecurityManager.setRealm(userRealm);
//        defaultSecurityManager.setSessionManager(defaultSecurityManager);//设置会话
        defaultSecurityManager.setCacheManager(cacheManager);//设置缓存
        return defaultSecurityManager;
    }

    /**
     * 身份认证realm; (这个需要自己写，账号密码校验；权限等)
     *
     * @return
     */

    @Bean//HashedCredentialsMatcher hashedCredentialsMatcher
    public UserRealm userRealm() {
        UserRealm userRealm = new UserRealm();
//        userRealm.setCredentialsMatcher(hashedCredentialsMatcher);
        return userRealm;
    }

}
